<template>
  <GoBack />
  <div>
    <div class="header">
      <a-row justify="center">
        <a-col :xs="22" :lg="16" :xl="15" :xxl="13">
          <div class="subject" :style="{ backgroundColor: subject.color }">
            <span>{{ subject.name }}</span>
          </div>
        </a-col>
      </a-row>
    </div>
    <div class="navi">
      <a-row justify="center">
        <a-col :xs="22" :lg="16" :xl="15" :xxl="13">
          <a-row justify="center">
            <a-col :xs="8">
              <div class="sub not-select">
                <span @click="switchCate(-1)">{{preCate}}</span>
              </div>
            </a-col>
            <a-col :xs="8">
              <div class="sub selected">
                <span>{{curCate}}</span>
              </div>
            </a-col>
            <a-col :xs="8">
              <div class="sub not-select">
                <span @click="switchCate(1)">{{ postCate }}</span>
              </div>
            </a-col>
          </a-row>
        </a-col>
      </a-row>
    </div>
    <a-divider><fire-filled style="color: red; font-size: 16px"/></a-divider>
    <div>
      <a-row justify="center">
        <a-col :xs="22" :lg="16" :xl="15" :xxl="13">
          <div class="problem-pad" v-show="cateQusNum > 0">
            <div class="pad-header">
              <span>{{ qusIdx + 1 }} / {{ cateQusNum }}</span>
              <span class="op op-color" @click="switchQus(-1)">上一题</span>
              <span class="op op-color" @click="switchQus(1)"><loading-outlined style="font-size: 0.9em" v-show="switchLoading"/>下一题</span>
              <span class="op" @click="showAns" :class="{ 'disabled': !enabledShowAns, 'op-color': enabledShowAns}">解析</span>
              <star-filled @click="addCollect" style="margin-left: 15px;color: #FFBD33;" v-show="collectStatus"/>
              <star-outlined @click="addCollect" style="margin-left: 15px; color: #868383;" v-show="!collectStatus"/>
            </div>
            <div class="problem" :style="{ boxShadow: ansResultColor }">
              <div class="qus-info">
                <a-tag color="purple">{{ qus.type }}</a-tag>
                <a-tag color="green" v-if="qus.type !== '0'">{{ qus.year }} 第{{ qus.number }}题</a-tag>
                <check-circle-filled style="color: #2ecc71"/>
                <span>{{ qus.acc }}%</span>
                <edit-filled style="color: #34495e"/>
                <span>{{ qus.try }}</span>
              </div>
              <div class="qus-info">
                <a-tag color="cyan" v-for="(v, idx) in qus.tag" :key="idx">{{v}}</a-tag>
              </div>
              <ShowProblem :content="qus.question"/>
              <div class="choice">
                <a-radio-group button-style="solid" v-model:value="curChoice" @change="onChoiceChange($event, qus.id)">
                  <a-radio-button value="A">A</a-radio-button>
                  <a-radio-button value="B">B</a-radio-button>
                  <a-radio-button value="C">C</a-radio-button>
                  <a-radio-button value="D">D</a-radio-button>
                </a-radio-group>
              </div>
            </div>
            <a-divider><bulb-filled style="font-size: 1.5em; color: #f1c40f"/></a-divider>
            <div class="answer" v-for="(ans, idx) in qus.answer" :key="idx" v-show="isShowAns">
              <div class="provider">
                <copyright-circle-outlined style="color: #9b59b6"/>
                <span>{{ ans.author }}</span>
              </div>
              <ShowProblem :content="ans.content"/>
            </div>
          </div>
          <div v-show="isShowAns" style="margin-top: 50px">
            <a-divider><comment-outlined style="font-size: 1.5em; color: #45e87f"/></a-divider>
            <OuterComment :uname="uname" :pid="qus.id"></OuterComment>
          </div>
        </a-col>
      </a-row>
    </div>
    <div class="footer">
      <span style="font-family:arial,serif;">Copyright &copy; 2022 Just for fun.</span>
    </div>
  </div>
</template>

<script lang="ts">
import { Col, Divider, message, Radio, Row, Tag } from 'ant-design-vue'
import {
  BulbFilled,
  CheckCircleFilled,
  CopyrightCircleOutlined,
  EditFilled,
  FireFilled,
  StarFilled,
  StarOutlined,
  LoadingOutlined,
  CommentOutlined
} from '@ant-design/icons-vue'
import { defineComponent, onBeforeUnmount, onMounted, onUnmounted, ref, watch } from 'vue'
import { useRoute } from 'vue-router'
import {
  createDefaultQusItem, KillRecord, QusItem,
  SolveLog, randSelect, Collect, transUrl,
  Breakpoint, HistoryAnswer
} from '@/utils/ds'
import {
  addRecordLog, getCategoryData, getTargetQus,
  addUserCollect, getUserCollect, deleteCollect,
  addBreakpoint, getUserHistoryAnswer, setUserHistoryAnswer
} from '@/service'
import { checkToken, decodeCT, decodeID, decodeValue, getUserName, subjectName2Code } from '@/utils/check'
import {
  CS_RANK, OS_RANK, NET_RANK,
  CCP_RANK, AnsFieldSeq, AnsSeq,
  BREAKPOINT_KEY, USER_COLLECT, CACHED_CHOICE
} from '@/utils/constants'
import ShowProblem from '@/components/ShowProblem.vue'
import GoBack from '@/components/GoBack.vue'
import OuterComment from '@/components/OuterComment.vue'
import { setCacheLongWithTime, getCacheLong, checkUserUpdateExpire, setCacheLong, setCache, getCache } from '@/utils/common'

interface CollectTuple {
  id: number,
  pid: number
}

interface SubjectCate {
  name: string,
  ids: number[]
}

interface Subject {
  name: string,
  color: string,
  category: SubjectCate[]
}

interface RawQus {
  ct: string,
  rt: string,
  lk: string
}

interface ChoicePair {
  choice: string,
  created: number,
  status: number
}

export default defineComponent({
  name: 'SolveProblem',
  components: {
    ShowProblem,
    FireFilled,
    LoadingOutlined,
    CommentOutlined,
    StarFilled,
    StarOutlined,
    CheckCircleFilled,
    EditFilled,
    BulbFilled,
    CopyrightCircleOutlined,
    ARow: Row,
    ACol: Col,
    ADivider: Divider,
    ATag: Tag,
    ARadioGroup: Radio.Group,
    ARadioButton: Radio.Button,
    GoBack,
    OuterComment
  },
  setup () {
    const route = useRoute()

    const userCollectHistory = ref<CollectTuple[]>([])
    const uname = ref<string>('K')
    const bkTag = ref<boolean>(false)
    const csIDS = ref<number[]>([])
    const osIDS = ref<number[]>([])
    const ccpIDS = ref<number[]>([])
    const netIDS = ref<number[]>([])

    const collectStatus = ref<boolean>(false)
    const curChoice = ref<string>('')
    const qus = ref<QusItem>(createDefaultQusItem())
    const isShowAns = ref<boolean>(false)
    const enabledShowAns = ref<boolean>(false)
    const switchLoading = ref<boolean>(false)
    const fakeRawQus = ref<RawQus>({
      ct: '',
      rt: '',
      lk: 'w'
    })

    const subject = ref<Subject>({
      name: 'Unknown',
      color: '#3498db',
      category: []
    })
    const preCate = ref<string>('')
    const curCate = ref<string>('')
    const postCate = ref<string>('')
    const cateIdx = ref<number>(-1)

    const cateQusNum = ref<number>(0)
    const qusIdx = ref<number>(-1)
    const loadedQus = ref<RawQus[]>([])
    const killRecord = ref<Map<number, KillRecord>>(new Map<number, KillRecord>())

    const ansRightColor = ref<string>('rgba(20, 220, 53, 0.8) 0 3px 8px')
    const ansWrongColor = ref<string>('rgba(215, 26, 26, 0.5) 0 3px 8px')
    const ansResultColor = ref<string>('')
    const lastSwitchQusTime = ref<number>(0)

    const cachedChoice = ref<Map<number, ChoicePair>>(new Map<number, ChoicePair>())

    const switchCate = (diff: number) => {
      const t = cateIdx.value + diff
      setCateName(t)
    }

    const setCateName = (i: number, qusCursor?: number) => {
      const s = subject.value
      if (s.category.length === 0) {
        return
      }
      const c = s.category
      const l = c.length
      // 初始化状态
      preCate.value = ''
      curCate.value = ''
      postCate.value = ''
      cateQusNum.value = 0
      qusIdx.value = -1
      // 清空已经加载的问题数组
      loadedQus.value.length = 0

      if (i < l && i >= 0) {
        curCate.value = c[i].name
        cateIdx.value = i
        cateQusNum.value = c[i].ids.length
        qusIdx.value = 0
      }
      if (i + 1 < l) {
        postCate.value = c[i + 1].name
      }
      if (i - 1 >= 0) {
        preCate.value = c[i - 1].name
      }
      if (qusCursor !== undefined) {
        qusIdx.value = qusCursor
        loadQus(qusCursor)
      } else {
        loadQus(0)
      }
    }

    const switchQus = (diff: number) => {
      if (cateQusNum.value < 1) {
        return
      }
      const t = qusIdx.value + diff
      if (t >= cateQusNum.value || t < 0) {
        return
      }

      const old = lastSwitchQusTime.value
      const cur = new Date().getTime()
      if (old === 0 || (cur > old && cur - old > 600)) {
        // 加载问题
        qusIdx.value = t
        loadQus(t)

        lastSwitchQusTime.value = cur
        return
      }

      const sleepTime = 500
      if (diff > 0 && !switchLoading.value) {
        switchLoading.value = true
        setTimeout(() => {
          // 加载问题
          qusIdx.value = t
          loadQus(t)

          switchLoading.value = false
        }, sleepTime)
      }
    }

    const resetQusState = () => {
      curChoice.value = ''
      isShowAns.value = false
      enabledShowAns.value = false
      ansResultColor.value = ''
      collectStatus.value = false
    }

    const rebuildQusState = () => {
      // 判断是否已经选择
      const id = qus.value.id
      const s = killRecord.value.get(id)
      if (s !== undefined) {
        curChoice.value = s.select
        enabledShowAns.value = true
        if (s.status === 1) {
          ansResultColor.value = ansRightColor.value
        } else {
          ansResultColor.value = ansWrongColor.value
        }
      } else {
        const choice = cachedChoice.value.get(id)
        if (choice !== undefined) {
          curChoice.value = choice.choice
          enabledShowAns.value = true
        }
      }
      const chidx = userCollectHistory.value.findIndex((value) => value.pid === id)
      if (chidx !== -1) {
        collectStatus.value = true
      }
    }

    const decodeCurrentQus = (idx: number) => {
      const loaded = loadedQus.value
      const qusRaw = loaded[idx]
      const key = decodeID(qusRaw.lk)
      const header = decodeValue(qusRaw.rt, key)
      const content = decodeCT(header, qusRaw.ct, key)
      if (content === undefined) {
        return
      }
      // 初始化与问题相关的状态
      resetQusState()

      const e = qus.value
      let v = content.get('id')
      e.id = v === undefined ? 0 : parseInt(v)

      v = content.get('year')
      e.year = v === undefined ? '' : v

      v = content.get('number')
      e.number = v === undefined ? 1 : parseInt(v)

      v = content.get('question')
      if (v !== undefined) {
        // v = v.replace(PORT_PAT, '')
        // v = v.replace(URL_PAT, IMG_HOST)
        v = transUrl(v)
        e.question = v
      } else {
        e.question = ''
      }

      v = content.get('tag')
      e.tag = v === undefined ? [] : v.split('#')

      v = content.get('type')
      e.type = v === undefined ? '408' : v
      if (e.type === '0') {
        e.type = '其他'
      }

      v = content.get('subject')
      e.subject = v === undefined ? 'Unknown' : v

      v = content.get('choice')
      e.choice = v === undefined ? 'X' : v

      v = content.get('answer')
      if (v !== undefined) {
        v = transUrl(v)
        const ansList = v.split(AnsSeq)
        e.answer.length = 0
        ansList.forEach(value => {
          const a = value.split(AnsFieldSeq)
          if (a[1] === '影峰') {
            a[1] = 'GY'
          }
          e.answer.push({ content: a[0], author: a[1] })
        })
      } else {
        e.answer = []
      }

      v = content.get('acc')
      e.acc = v === undefined ? 0 : parseInt(v)

      v = content.get('try_')
      e.try = v === undefined ? 0 : parseInt(v)

      rebuildQusState()
    }

    const loadQus = (queryIdx: number) => {
      const loaded = loadedQus.value
      const totalQusNum = cateQusNum.value
      if (totalQusNum === 0 || queryIdx >= totalQusNum) {
        return
      }

      const loadedLen = loaded.length
      const batch = 10
      if (loadedLen === 0 && queryIdx > 0) {
        for (let i = 0; i < queryIdx; i++) {
          loaded.push(fakeRawQus.value)
        }
      }

      const sub = subject.value
      const cate = sub.category[cateIdx.value]
      const cateIds = cate.ids
      const requestId: number[] = []

      if (queryIdx < loadedLen) {
        const qus = loaded[queryIdx]
        if (qus.lk === 'w') {
          requestId.push(cateIds[queryIdx])
          triggerLoadQus(requestId, queryIdx)
        } else {
          decodeCurrentQus(queryIdx)
        }
        return
      }

      if (queryIdx >= loaded.length) {
        const upBound:number = Math.min(batch + queryIdx, cateIds.length)
        for (let i = queryIdx; i < upBound; i++) {
          requestId.push(cateIds[i])
        }
        if (requestId.length === 0) {
          return
        }
        triggerLoadQus(requestId, queryIdx)
      }
    }

    const triggerLoadQus = (requestId: number[], queryIdx:number) => {
      // 加载题目
      getTargetQus(requestId)
        .then((response) => {
          if (response.status === 200) {
            const resp = response.data
            if (resp.code !== 0 || resp.data === null) {
              return
            }
            const data: Array<RawQus> = resp.data
            if (queryIdx < loadedQus.value.length) {
              loadedQus.value[queryIdx] = data[0]
            } else {
              data.forEach(e => {
                loadedQus.value.push(e)
              })
            }
            decodeCurrentQus(queryIdx)
          }
        })
        .catch((err) => {
          console.log(err)
        })
    }

    const setSubjectInfo = (name:string, data: any) => {
      let readName = 'Unknown'
      let showColor = '#3498db'
      if (data === null || data.lk === undefined) {
        message.error('题目数据加载出错，请重新登录后加载')
        return
      }
      let rankList: string[] = []
      if (name === 'CS') {
        readName = '数据结构'
        rankList = CS_RANK
        showColor = '#3498db'
      } else if (name === 'CCP') {
        readName = '组成原理'
        showColor = '#9b59b6'
        rankList = CCP_RANK
      } else if (name === 'NET') {
        readName = '计算机网络'
        showColor = '#e67e22'
        rankList = NET_RANK
      } else if (name === 'OS') {
        readName = '操作系统'
        showColor = '#1abc9c'
        rankList = OS_RANK
      } else if (name === 'RAND') {
        readName = '养生刷题'
        showColor = '#e74c3c'
      } else if (name === 'YEAR_IDX') {
        readName = '顺序刷题'
        showColor = '#f1c40f'
      }
      const sub = subject.value
      sub.name = readName
      sub.color = showColor
      const lk = data.lk
      const key = decodeID(lk)
      if (name === 'RAND') {
        if (csIDS.value.length === 0) {
          const cs = decodeValue(data.CS as string, key)
          const ccp = decodeValue(data.CCP as string, key)
          const os = decodeValue(data.OS as string, key)
          const net = decodeValue(data.NET as string, key)
          csIDS.value = cs.split('.').map((x) => parseInt(x))
          osIDS.value = os.split('.').map((x) => parseInt(x))
          ccpIDS.value = ccp.split('.').map((x) => parseInt(x))
          netIDS.value = net.split('.').map((x) => parseInt(x))
        }

        const genIds:number[] = []
        let ids_ = randSelect(csIDS.value, 7)
        genIds.push(...ids_)

        ids_ = randSelect(ccpIDS.value, 4)
        genIds.push(...ids_)

        ids_ = randSelect(osIDS.value, 6)
        genIds.push(...ids_)

        ids_ = randSelect(netIDS.value, 3)
        genIds.push(...ids_)

        sub.category.push({
          name: '随机题目',
          ids: genIds
        })
        return
      }

      const temp:SubjectCate[] = []
      for (const k in data) {
        if (k === 'lk' || k === 'all' || k === 'acc' || k === 'num') {
          continue
        }
        if (!Object.hasOwnProperty.call(data, k)) {
          continue
        }
        const ids = decodeValue(data[k], key)
        temp.push({
          name: k,
          ids: ids.split('.').map(x => parseInt(x))
        })
      }
      if (name !== 'YEAR_IDX') {
        sub.category = resortSubCate(rankList, temp)
      } else {
        sub.category = temp
      }

      if (bkTag.value) {
        // console.log(sub.category)
        bkTag.value = false
        const bk = sessionStorage.getItem(BREAKPOINT_KEY)
        if (bk !== null) {
          let cateName = ''
          let pidIdx = -1
          const breakpoint = JSON.parse(bk)
          for (let i = 0; i < breakpoint.length; i++) {
            const b = breakpoint[i]
            if (b.subject === name || (b.subject === 'SEQ' && name === 'YEAR_IDX')) {
              cateName = b.category
              pidIdx = b.idx
              break
            }
          }
          if (cateName === '') {
            setCateName(0)
          } else {
            const resetCateIdx = sub.category.findIndex(x => x.name === cateName)
            if (resetCateIdx !== -1) {
              setCateName(resetCateIdx, pidIdx)
            } else {
              setCateName(0)
            }
          }
        }
        return
      }
      setCateName(0)
    }

    const resortSubCate = (rank:string[], src:SubjectCate[]) => {
      if (rank.length === 0) {
        return src
      }
      const arr:SubjectCate[] = []
      const cate = src
      const visited:boolean[] = []
      for (let i = 0; i < cate.length; i++) {
        visited.push(false)
      }
      rank.forEach((t) => {
        const i = cate.findIndex(value => value.name === t)
        if (i !== -1) {
          arr.push(cate[i])
          visited[i] = true
        }
      })
      for (let i = 0; i < visited.length; i++) {
        if (!visited[i]) {
          arr.push(cate[i])
        }
      }
      return arr
    }

    const getCateData = (cate: string) => {
      if (cate.length === 0) {
        message.error('出错了！')
        return
      }
      let SUBJECT_KEY = cate.toUpperCase()
      const candidate = ['CS', 'CCP', 'NET', 'OS', 'SEQ', 'FUN']
      if (candidate.indexOf(SUBJECT_KEY) === -1) {
        message.error('未知科目')
        return
      }
      if (SUBJECT_KEY === 'SEQ') {
        SUBJECT_KEY = 'YEAR_IDX'
      }
      if (SUBJECT_KEY === 'FUN') {
        SUBJECT_KEY = 'RAND'
      }
      const cache = getCacheLong(SUBJECT_KEY)
      if (cache.length > 0) {
        const d = JSON.parse(cache)
        if (checkUserUpdateExpire(d.time)) {
          setSubjectInfo(SUBJECT_KEY, d.data)
          return
        }
      }

      getCategoryData(SUBJECT_KEY)
        .then((response) => {
          if (response.status !== 200) {
            return
          }
          const resp = response.data
          if (resp.code !== 0) {
            message.error(resp.msg, 0.5)
            return
          }
          const data = resp.data
          setCacheLongWithTime(SUBJECT_KEY, data)
          setSubjectInfo(SUBJECT_KEY, data)
        })
        .catch((err) => {
          console.log(err)
        })
    }

    const showAns = () => {
      if (curChoice.value === '' || !enabledShowAns.value || isShowAns.value) {
        return
      }
      isShowAns.value = true
      const ans = qus.value.choice.toUpperCase()
      if (curChoice.value === ans) {
        ansResultColor.value = ansRightColor.value
      } else {
        ansResultColor.value = ansWrongColor.value
      }
      if (ans === 'X') {
        return
      }
      const h = killRecord.value
      const id = qus.value.id
      if (!h.has(id)) {
        const c = curChoice.value
        const tc = qus.value.choice
        const created = new Date().getTime()
        h.set(id, { select: c, status: c === tc ? 1 : 0, pid: qus.value.id, created: created })
      }
    }

    const collectSet = ref<Map<number, number>>(new Map<number, number>())
    const addCollect = () => {
      const origin = collectStatus.value
      collectStatus.value = !collectStatus.value
      const curQusId = qus.value.id
      if (curQusId === 0) {
        return
      }
      const e = collectSet.value.get(curQusId)
      if (e !== undefined) {
        if (origin) {
          collectSet.value.set(curQusId, 0)
        } else {
          collectSet.value.set(curQusId, new Date().getTime())
        }
      } else {
        if (origin) {
          const idx = userCollectHistory.value.findIndex(value => value.pid === curQusId)
          if (idx !== -1) {
            deleteCollect(userCollectHistory.value[idx].id)
            userCollectHistory.value.splice(idx, 1)
            sessionStorage.setItem(USER_COLLECT, JSON.stringify(userCollectHistory.value))
          }
        } else {
          collectSet.value.set(curQusId, new Date().getTime())
        }
      }
    }

    const leaveSubmitCollect = () => {
      const s = collectSet.value
      const token = checkToken()
      const uid = decodeID(token)
      if (uid === 0) {
        return
      }
      const d:Collect[] = []
      s.forEach((v, k) => {
        if (v !== 0) {
          d.push({
            pid: k,
            created: v,
            category: 0
          })
        }
      })

      if (d.length > 0) {
        addUserCollect(d)
          .then((response) => {
            if (response.status === 200) {
              const data = response.data
              if (data.code === 0) {
                // console.log(data)
              }
            }
          })
          .catch((err) => {
            console.log(err)
          })
      }
    }

    const submitKillRecord = () => {
      setCacheLong(CACHED_CHOICE, JSON.stringify(cachedChoice.value))
      const token:string = checkToken()
      if (token === '') {
        return
      }
      const uid = decodeID(token)
      const h = killRecord.value
      const data: SolveLog[] = []
      if (h.size > 0) {
        h.forEach(v => {
          data.push({
            uid: uid,
            pid: v.pid,
            status: v.status,
            created: v.created
          })
        })

        addRecordLog(data)
          .then((response) => {
            if (response.status !== 200) {
              return
            }
            const resp = response.data
            if (resp.code === 0) {
              h.clear()
            }
          })
          .catch((err) => {
            console.log(err)
          })
      }
    }

    const submitDataOnLeave = () => {
      submitKillRecord()

      leaveSubmitCollect()

      submitBreakpoint()

      submitHistoryChoice()
    }

    const submitBreakpoint = () => {
      const subjectCode = subjectName2Code(subject.value.name)
      if (subjectCode.length === 0) {
        return
      }
      const i = cateIdx.value
      if (i < 0 || killRecord.value.size === 0) {
        return
      }
      const qid = subject.value.category[i].ids[qusIdx.value]
      const breakpoint: Breakpoint = {
        id: 0,
        pid: qid,
        idx: qusIdx.value,
        subject: subjectCode,
        category: curCate.value
      }
      // const bk = sessionStorage.getItem(BREAKPOINT_KEY)
      const bk = getCache(BREAKPOINT_KEY)
      let hit = false
      let restoreBk = null
      if (bk.length > 0) {
        restoreBk = JSON.parse(bk)
        for (let j = 0; j < restoreBk.length; j++) {
          const b = restoreBk[j]
          if (b.subject === breakpoint.subject) {
            b.pid = breakpoint.pid
            b.idx = breakpoint.idx
            b.category = breakpoint.category
            breakpoint.id = b.id
            hit = true
            break
          }
        }
      }
      if (!hit && restoreBk !== null) {
        restoreBk.push({
          id: 0,
          uid: 0,
          pid: breakpoint.pid,
          idx: breakpoint.idx,
          subject: breakpoint.subject,
          category: breakpoint.category,
          created: ''
        })
      }
      setCache(BREAKPOINT_KEY, JSON.stringify(restoreBk))
      addBreakpoint(breakpoint)
    }

    const loadUserCollect = () => {
      const cacheCollect = sessionStorage.getItem(USER_COLLECT)
      if (cacheCollect !== null) {
        userCollectHistory.value = JSON.parse(cacheCollect)
      }
      getUserCollect()
        .then(response => {
          if (response.status === 200) {
            const resp = response.data
            if (resp.code === 0 && resp.data !== null) {
              const collect: CollectTuple[] = []
              resp.data.forEach((item:any) => {
                collect.push({
                  id: item.id,
                  pid: item.pid
                })
              })
              sessionStorage.setItem(USER_COLLECT, JSON.stringify(collect))
              userCollectHistory.value = collect
            }
          }
        })
    }

    const onChoiceChange = (e: Event, pid: number) => {
      const c = curChoice.value
      if (c !== '') {
        let status = 2
        if (cachedChoice.value.has(pid)) {
          status = 1
        }
        const choice: ChoicePair = {
          choice: c,
          created: new Date().getTime(),
          status: status
        }
        cachedChoice.value.set(pid, choice)
      }
    }

    const submitHistoryChoice = () => {
      const sub = subjectName2Code(subject.value.name)
      if (sub.length === 0) {
        return
      }
      const e = cachedChoice.value
      const dataSend: HistoryAnswer[] = []
      const cachedString: string[] = []
      e.forEach((value, key) => {
        cachedString.push(`${key}=${value.choice}`)
        if (value.status > 0) {
          const u: HistoryAnswer = {
            id: 0,
            uid: 0,
            pid: key,
            choice: value.choice,
            created: value.created
          }
          dataSend.push(u)
        }
      })
      if (dataSend.length > 0) {
        setUserHistoryAnswer(sub, dataSend)
          .then(response => {
            if (response.status !== 200) {
              return
            }
            const resp = response.data
            if (resp.code !== 0 || resp.data === null) {
              return
            }
            cachedChoice.value.clear()
            setCache(`${CACHED_CHOICE}_${sub}`, cachedString.join('#'))
          })
      }
    }

    const initHistoryAnswer = () => {
      // get from sessionStorage
      const sub = subjectName2Code(subject.value.name)
      const cached = getCache(`${CACHED_CHOICE}_${sub}`)
      if (cached.length > 0) {
        cachedChoice.value.clear()
        const e = cached.split('#')
        e.forEach(v => {
          const u = v.split('=')
          const pid = parseInt(u[0])
          const f = u[1].split(',')
          const c: ChoicePair = {
            choice: f[0],
            created: 0,
            status: 0
          }
          cachedChoice.value.set(pid, c)
        })
        return
      }

      getUserHistoryAnswer(sub)
        .then(response => {
          if (response.status !== 200) {
            return
          }
          const resp = response.data
          if (resp.code !== 0 || resp.data === null) {
            return
          }
          cachedChoice.value.clear()
          for (const e in resp.data) {
            const pid = parseInt(e)
            const f = resp.data[e].split(',')
            const w: ChoicePair = {
              status: 0,
              created: 0,
              choice: f[0]
            }
            cachedChoice.value.set(pid, w)
          }
        })
    }

    onMounted(() => {
      // load user collection
      loadUserCollect()
      uname.value = getUserName()
      message.info('正在加载数据...', 0.3)
      const targetCate = route.params.cate as string
      if (targetCate.startsWith('bk')) {
        bkTag.value = true
        const i = targetCate.indexOf('_')
        getCateData(targetCate.substring(i + 1, targetCate.length))
      } else {
        getCateData(targetCate)
      }

      // addListener
      window.addEventListener('beforeunload', submitDataOnLeave)

      // reset history choice
      initHistoryAnswer()
    })

    watch(curChoice, (curChoice) => {
      if (!enabledShowAns.value && curChoice !== '') {
        enabledShowAns.value = true
      }
    })

    onBeforeUnmount(() => {
      submitDataOnLeave()
    })

    onUnmounted(() => {
      window.removeEventListener('beforeunload', submitDataOnLeave)
    })

    return {
      uname,
      subject,
      preCate,
      curCate,
      postCate,
      cateIdx,
      cateQusNum,
      collectStatus,
      qus,
      qusIdx,
      curChoice,
      isShowAns,
      enabledShowAns,
      ansResultColor,
      switchLoading,
      switchCate,
      addCollect,
      switchQus,
      showAns,
      onChoiceChange
    }
  }
})
</script>

<style scoped>
.header {
  padding: 20px 0 20px 0;
}
.header .subject {
  height: 60px;
  width: 240px;
  color: #ffffff;
  background-color: #3498db;
  clip-path: polygon(0 0, 100% 0, 85% 50%, 100% 100%, 0 100%, 15% 50%);
  padding: 10px;
  text-align: center;
  margin: auto;
}
.header .subject span {
  font-size: 2em;
}

.navi {
  margin-top: 25px;
}

.navi .sub {
  text-align: center;
}

.navi .sub span {
  cursor: pointer;
  display: inline-block;
  margin: 0 5px;
}

.navi .not-select span{
  border-bottom: 2px solid #aeb8c2;
  font-size: 1em;
}

.navi .selected span{
  font-size: 1.2em;
  padding: 2px 8px;
  border-radius: 10px;
  color: #ffffff;
  background-color: #1abc9c;
}

.problem-pad {
  margin-top: 10px;
}

.problem-pad .problem {
  border-radius: 10px;
  padding: 0 15px;
  box-shadow: rgba(0, 0, 0, 0.25) 0 3px 8px;
}

.problem-pad .pad-header {
  margin-bottom: 18px;
}

.problem-pad .pad-header span{
  display: inline-block;
  font-size: 1.3em;
  padding: 0 5px;
  cursor: pointer;
}

.problem-pad .pad-header .op-color {
  background-color: #1abc9c;
}

.problem-pad .pad-header .disabled {
  background-color:#6f6e6e
}

.problem-pad .pad-header .op {
  margin-left: 10px;
  border-radius: 8px;
  color: white;
}

.problem-pad .problem .qus-info span {
  display: inline-block;
  font-size: 1.2em;
  margin-top: 5px;
}

.problem-pad .problem .qus-info span:not(:first-child) {
  margin-left: 10px;
}

.problem-pad .problem .choice {
  padding: 20px 0 10px 0;
}

.problem-pad .answer {
  border-radius: 10px;
  padding: 0 15px;
  box-shadow: rgba(170, 63, 63, 0.25) 0 3px 8px;
  margin: 25px 0;
  background-color: #f3f3f3;
}

.problem-pad .answer .provider {
  padding-top: 10px;
}
.problem-pad .answer .provider span{
  font-size: 1.2em;
  padding: 2px;
  font-weight: bold;
  letter-spacing: 1px;
}

.footer {
  text-align: center;
  margin-top: 10px;
  margin-bottom: 5px;
  padding: 5px;
}
.footer span {
  display: inline-block;
  font-weight: 400;
}
</style>
